#pragma once

namespace bs
{

#define DECLARE_COMMAND_MAP()  public: \
	                               virtual void Execute(const Command& cmd);

#define BEGIN_COMMAND_MAP(theClass)  void theClass::Execute(const Command& cmd) \
	                                      {

#define COMMAND_MAP_ENTRY(type, code, func)  if(cmd.GetType()==type && cmd.GetCode()==code) \
	                                            { \
	                                               func(cmd); \
                                                } \
											 else

#define END_COMMAND_MAP()  {} }


	class Command;

	class ICommandProcessor
	{
	public:
		ICommandProcessor() {}
		virtual ~ICommandProcessor() {}

	public:
		virtual void Execute(const Command& cmd) = 0;
	};


	class Command
	{
	public:
		Command(int type, int code) : type(type), code(code), value(0), result(0), sender(0), param(0), src(0), dst(0) {}
		Command() : type(0), code(0), value(0), result(0), sender(0), param(0), src(0), dst(0) {}
		~Command() {}

		void SetType(int type) { this->type = type; }
		void SetCode(int code) { this->code = code; }
		void SetValue(int value) { this->value = value; }
		void SetResult(void* result) { this->result = result; }
		void SetSender(void* sender) { this->sender = sender; }
		void SetParam(void* param) { this->param = param; }
		void SetSrc(void* src) { this->src = src; }
		void SetDst(void* dst) { this->dst = dst; }

		int GetType() const { return this->type; }
		int GetCode() const { return this->code; }
		int GetValue() const { return this->value; }
		void* GetResult() const { return this->result; }
		void* GetSender() const { return this->sender; }
		void* GetParam() const { return this->param; }
		void* GetSrc() const { return this->src; }
		void* GetDst() const { return this->dst; }

	private:
		int type;
		int code;
		int value;
		void* result;      // sometimes returns sth when necessarily
		void* sender;    // the sender will not be the src, it may be the third party
		void* param;
		void* src;
		void* dst;
	};

}
